Skip to content

Method: requestPlayerData(InputProvider, String)

1: package de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.impl;
2:
3: import java.util.ArrayList;
4: import java.util.LinkedHashMap;
5: import java.util.LinkedHashSet;
6: import java.util.List;
7: import java.util.Map;
8: import java.util.Optional;
9: import java.util.Set;
10: import java.util.regex.Pattern;
11:
12: import de.fhdw.gaming.core.domain.GameBuilder;
13: import de.fhdw.gaming.core.domain.GameBuilderFactory;
14: import de.fhdw.gaming.core.domain.GameException;
15: import de.fhdw.gaming.core.domain.Strategy;
16: import de.fhdw.gaming.core.ui.InputProvider;
17: import de.fhdw.gaming.core.ui.InputProviderException;
18: import de.fhdw.gaming.core.ui.type.validator.MaxValueValidator;
19: import de.fhdw.gaming.core.ui.type.validator.MinValueValidator;
20: import de.fhdw.gaming.core.ui.type.validator.PatternValidator;
21: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.KopfundZahlundKanteAnswerEnum;
22: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.KopfundZahlundKanteGameBuilder;
23: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.KopfundZahlundKanteGameBuilderFactory;
24: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.KopfundZahlundKantePlayer;
25: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.KopfundZahlundKantePlayerBuilder;
26: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.KopfundZahlundKanteStrategy;
27: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.factory.KopfundZahlDefaultStrategyFactoryProvider;
28: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.factory.KopfundZahlStrategyFactory;
29: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.domain.factory.KopfundZahlStrategyFactoryProvider;
30: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.moves.factory.KopfundZahlundKanteMoveFactory;
31: import de.fhdw.gaming.ipspiel22.kopfundzahlundkante.moves.impl.DefaultKopfundZahlundKanteMoveFactory;
32:
33: /**
34: * Implements {@link KopfundZahlundKanteGameBuilderFactory} by creating a KopfundZahl game builder.
35: */
36: public final class KopfundZahlundKanteGameBuilderFactoryImpl implements KopfundZahlundKanteGameBuilderFactory {
37:
38: /**
39: * The number of players.
40: */
41: private static final int NUMBER_OF_PLAYERS = 2;
42:
43: /**
44: * Smallest allowed maximum computation time per move in seconds.
45: */
46: private static final int MIN_MAX_COMPUTATION_TIME_PER_MOVE = 1;
47:
48: /**
49: * Largest allowed maximum computation time per move in seconds.
50: */
51: private static final int MAX_MAX_COMPUTATION_TIME_PER_MOVE = 3600;
52:
53: /**
54: * All available Head and Tail strategies.
55: */
56: private final Set<KopfundZahlundKanteStrategy> strategies;
57:
58: /**
59: * Creates a Head and Tail game factory. Head and Tail strategies are loaded
60: * by using the {@link java.util.ServiceLoader}.
61: * <p>
62: * This constructor is meant to be used by the {@link java.util.ServiceLoader}.
63: */
64: public KopfundZahlundKanteGameBuilderFactoryImpl() {
65: this(new KopfundZahlDefaultStrategyFactoryProvider());
66: }
67:
68: /**
69: * Creates a Head and Tail game factory.
70: *
71: * @param strategyFactoryProvider The {@link KopfundZahlStrategyFactoryProvider} for loading Head and
72: * Tail strategies.
73: */
74: KopfundZahlundKanteGameBuilderFactoryImpl(final KopfundZahlDefaultStrategyFactoryProvider strategyFactoryProvider) {
75: final KopfundZahlundKanteMoveFactory moveFactory = new DefaultKopfundZahlundKanteMoveFactory();
76:
77: final List<KopfundZahlStrategyFactory> factories = strategyFactoryProvider.getStrategyFactories();
78: this.strategies = new LinkedHashSet<>();
79: for (final KopfundZahlStrategyFactory factory : factories) {
80: this.strategies.add(factory.create(moveFactory));
81: }
82: }
83:
84: @Override
85: public String getName() {
86: return "KopfundZahlundKante";
87: }
88:
89: @Override
90: public int getMinimumNumberOfPlayers() {
91: return KopfundZahlundKanteGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
92: }
93:
94: @Override
95: public int getMaximumNumberOfPlayers() {
96: return KopfundZahlundKanteGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
97: }
98:
99: @Override
100: public List<? extends Strategy<?, ?, ?>> getStrategies() {
101: return new ArrayList<>(this.strategies);
102: }
103:
104: @Override
105: public KopfundZahlundKanteGameBuilder createGameBuilder(final InputProvider inputProvider) throws GameException {
106: try {
107: final KopfundZahlundKanteGameBuilder gameBuilder = new KopfundZahlundKanteGameBuilderImpl();
108:
109: @SuppressWarnings("unchecked")
110: final Map<String, Object> gameData = inputProvider.needInteger(
111: GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE,
112: "Maximum computation time per move in seconds",
113: Optional.of(GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE),
114: new MinValueValidator<>(
115: KopfundZahlundKanteGameBuilderFactoryImpl.MIN_MAX_COMPUTATION_TIME_PER_MOVE),
116: new MaxValueValidator<>(
117: KopfundZahlundKanteGameBuilderFactoryImpl.MAX_MAX_COMPUTATION_TIME_PER_MOVE))
118: .requestData("Game properties");
119:
120: gameBuilder.changeMaximumComputationTimePerMove(
121: (Integer) gameData.get(GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE));
122:
123: final InputProvider firstPlayerInputProvider = inputProvider.getNext(gameData);
124: final Map<String, Object> firstPlayerData = this.requestPlayerData(firstPlayerInputProvider, "Player 1");
125: final KopfundZahlundKantePlayer firstPlayer = this.createPlayer(gameBuilder.createPlayerBuilder(),
126: firstPlayerData);
127: final KopfundZahlundKanteStrategy firstPlayerStrategy = this.getStrategy(firstPlayerData);
128: gameBuilder.addPlayer(firstPlayer, firstPlayerStrategy);
129:
130: final InputProvider secondPlayerInputProvider = firstPlayerInputProvider.getNext(firstPlayerData);
131: final Map<String, Object> secondPlayerData = this.requestPlayerData(secondPlayerInputProvider, "Player 2");
132: final KopfundZahlundKantePlayer secondPlayer = this.createPlayer(gameBuilder.createPlayerBuilder(),
133: secondPlayerData);
134: final KopfundZahlundKanteStrategy secondPlayerStrategy = this.getStrategy(secondPlayerData);
135: gameBuilder.addPlayer(secondPlayer, secondPlayerStrategy);
136:
137: return gameBuilder;
138: } catch (final InputProviderException e) {
139: throw new GameException(String.format("Creating KopfundZahl game was aborted: %s", e.getMessage()), e);
140: }
141: }
142:
143: /**
144: * Returns data for a player builder.
145: *
146: * @param inputProvider The input provider.
147: * @param title The title for the UI.
148: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
149: * dialog).
150: */
151: @SuppressWarnings("unchecked")
152: private Map<String, Object> requestPlayerData(final InputProvider inputProvider, final String title)
153: throws GameException, InputProviderException {
154:• if (title.equals("Player 1")) {
155: inputProvider
156: .needString(
157: GameBuilderFactory.PARAM_PLAYER_NAME,
158: "Name",
159: Optional.empty(),
160: new PatternValidator(Pattern.compile("\\S+(\\s+\\S+)*")))
161: .needInteger(
162: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_TAIL,
163: "Player's outcome on Tail/Tail",
164: Optional.of(1))
165: .needInteger(
166: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_HEAD,
167: "Player's outcome on Tail/Head",
168: Optional.of(-1))
169: .needInteger(
170: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_TAIL,
171: "Player's outcome on Head/Tail",
172: Optional.of(-1))
173: .needInteger(
174: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_HEAD,
175: "Player's outcome on Head/Head",
176: Optional.of(1))
177: .needInteger(
178: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_HEAD,
179: "Player's outcome on Edge/Head",
180: Optional.of(-1))
181: .needInteger(
182: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_EDGE,
183: "Player's outcome on Head/Edge",
184: Optional.of(-1))
185: .needInteger(
186: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_TAIL,
187: "Player's outcome on Edge/Tail",
188: Optional.of(-1))
189: .needInteger(
190: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_EDGE,
191: "Player's outcome on Tail/Edge",
192: Optional.of(-1))
193: .needInteger(
194: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_EDGE,
195: "Player's outcome on Edge/Edge",
196: Optional.of(1))
197: .needObject(GameBuilderFactory.PARAM_PLAYER_STRATEGY, "Strategy", Optional.empty(),
198: this.strategies);
199:
200: } else {
201: inputProvider
202: .needString(
203: GameBuilderFactory.PARAM_PLAYER_NAME,
204: "Name",
205: Optional.empty(),
206: new PatternValidator(Pattern.compile("\\S+(\\s+\\S+)*")))
207: .needInteger(
208: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_TAIL,
209: "Player's outcome on Tail/Tail",
210: Optional.of(-1))
211: .needInteger(
212: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_HEAD,
213: "Player's outcome on Tail/Head",
214: Optional.of(1))
215: .needInteger(
216: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_TAIL,
217: "Player's outcome on Head/Tail",
218: Optional.of(1))
219: .needInteger(
220: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_HEAD,
221: "Player's outcome on Head/Head",
222: Optional.of(-1))
223: .needInteger(
224: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_HEAD,
225: "Player's outcome on Edge/Head",
226: Optional.of(1))
227: .needInteger(
228: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_EDGE,
229: "Player's outcome on Head/Edge",
230: Optional.of(1))
231: .needInteger(
232: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_TAIL,
233: "Player's outcome on Edge/Tail",
234: Optional.of(1))
235: .needInteger(
236: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_EDGE,
237: "Player's outcome on Tail/Edge",
238: Optional.of(1))
239: .needInteger(
240: KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_EDGE,
241: "Player's outcome on Edge/Edge",
242: Optional.of(-1))
243: .needObject(GameBuilderFactory.PARAM_PLAYER_STRATEGY, "Strategy", Optional.empty(),
244: this.strategies);
245:
246: }
247: return inputProvider.requestData(title);
248: }
249:
250: /**
251: * Creates a KopfundZahl player.
252: *
253: * @param playerBuilder The player builder.
254: * @param playerData The requested player data.
255: * @return The created {@link KopfundZahlundKantePlayer}.
256: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
257: * dialog).
258: */
259: private KopfundZahlundKantePlayer createPlayer(final KopfundZahlundKantePlayerBuilder playerBuilder,
260: final Map<String, Object> playerData) throws GameException, InputProviderException {
261:
262: final Map<KopfundZahlundKanteAnswerEnum,
263: Map<KopfundZahlundKanteAnswerEnum, Double>> possibleOutcomes = new LinkedHashMap<>();
264:
265: final Map<KopfundZahlundKanteAnswerEnum, Double> possibleOutcomesTail = new LinkedHashMap<>();
266: possibleOutcomesTail.put(
267: KopfundZahlundKanteAnswerEnum.TAIL,
268: (double) (Integer) playerData
269: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_TAIL));
270: possibleOutcomesTail.put(
271: KopfundZahlundKanteAnswerEnum.EDGE,
272: (double) (Integer) playerData
273: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_EDGE));
274: possibleOutcomesTail.put(
275: KopfundZahlundKanteAnswerEnum.HEAD,
276: (double) (Integer) playerData
277: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_TAIL_HEAD));
278: possibleOutcomes.put(KopfundZahlundKanteAnswerEnum.TAIL, possibleOutcomesTail);
279:
280: final Map<KopfundZahlundKanteAnswerEnum, Double> possibleOutcomesHead = new LinkedHashMap<>();
281: possibleOutcomesHead.put(
282: KopfundZahlundKanteAnswerEnum.TAIL,
283: (double) (Integer) playerData
284: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_TAIL));
285: possibleOutcomesHead.put(
286: KopfundZahlundKanteAnswerEnum.EDGE,
287: (double) (Integer) playerData
288: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_EDGE));
289: possibleOutcomesHead.put(
290: KopfundZahlundKanteAnswerEnum.HEAD,
291: (double) (Integer) playerData
292: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_HEAD_HEAD));
293: possibleOutcomes.put(KopfundZahlundKanteAnswerEnum.HEAD, possibleOutcomesHead);
294:
295: final Map<KopfundZahlundKanteAnswerEnum, Double> possibleOutcomesEdge = new LinkedHashMap<>();
296: possibleOutcomesEdge.put(
297: KopfundZahlundKanteAnswerEnum.TAIL,
298: (double) (Integer) playerData
299: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_TAIL));
300: possibleOutcomesEdge.put(
301: KopfundZahlundKanteAnswerEnum.EDGE,
302: (double) (Integer) playerData
303: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_EDGE));
304: possibleOutcomesEdge.put(
305: KopfundZahlundKanteAnswerEnum.HEAD,
306: (double) (Integer) playerData
307: .get(KopfundZahlundKanteGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_EDGE_HEAD));
308: possibleOutcomes.put(KopfundZahlundKanteAnswerEnum.EDGE, possibleOutcomesEdge);
309:
310: return playerBuilder.changeName((String) playerData.get(GameBuilderFactory.PARAM_PLAYER_NAME))
311: .changePossibleOutcomes(possibleOutcomes).build();
312: }
313:
314: /**
315: * Returns a KopfundZahl strategy.
316: *
317: * @param playerData The requested player data.
318: * @return The KopfundZahl strategy.
319: */
320: private KopfundZahlundKanteStrategy getStrategy(final Map<String, Object> playerData) {
321: return (KopfundZahlundKanteStrategy) playerData.get(GameBuilderFactory.PARAM_PLAYER_STRATEGY);
322: }
323:
324: }